package com.ruoyi.material.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.constant.material.PurchaseConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.material.domain.*;
import com.ruoyi.material.domain.vo.WarehouseInProductVO;
import com.ruoyi.material.mapper.*;
import com.ruoyi.material.service.IWarehouseInService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 入库单Service业务层处理
 *
 * @author wng
 * @date 2024-08-04
 */
@Service
public class WarehouseInServiceImpl implements IWarehouseInService {
    @Resource
    private WarehouseInMapper warehouseInMapper;
    @Resource
    private WarehouseInProductMapper warehouseInProductMapper;
    @Resource
    private PurchaseOrderProductMapper purchaseOrderProductMapper;
    @Resource
    private WarehouseStockMapper warehouseStockMapper;
    @Resource
    private WarehouseStockRecordMapper warehouseStockRecordMapper;
    @Resource
    private PurchaseOrderMapper purchaseOrderMapper;

    /**
     * 查询入库单
     *
     * @param id 入库单主键
     * @return 入库单
     */
    @Override
    public WarehouseIn selectWarehouseInById(Long id) {
        WarehouseIn warehouseIn = warehouseInMapper.selectWarehouseInById(id);

        List<WarehouseInProduct> products = warehouseInProductMapper.selectWarehouseInProductList(new WarehouseInProduct() {{
            setId(id);
        }});

        List<WarehouseInProductVO> productVOS = new ArrayList<>(10);

        products.forEach(item -> {
            WarehouseInProductVO vo = new WarehouseInProductVO();
            BeanUtils.copyProperties(item, vo);

            PurchaseOrderProduct orderProduct = purchaseOrderProductMapper.selectPurchaseOrderProductById(item.getPopId());
            //剩余数量，物品关联原数量减去入库数量
            vo.setRemainAmount(orderProduct.getQuantity().subtract(item.getQuantity()));
            productVOS.add(vo);
        });

        warehouseIn.getParams().put("products", productVOS);

        return warehouseIn;
    }

    /**
     * 查询入库单列表
     *
     * @param warehouseIn 入库单
     * @return 入库单
     */
    @Override
    public List<WarehouseIn> selectWarehouseInList(WarehouseIn warehouseIn) {
        if (warehouseIn.getParams() != null) {
            if (warehouseIn.getParams().containsKey("createTimeStart") && warehouseIn.getParams().containsKey("createTimeEnd")) {
                if (warehouseIn.getParams().get("createTimeStart") != null && !"".equals(warehouseIn.getParams().get("createTimeStart"))
                        && warehouseIn.getParams().get("createTimeEnd") != null && !"".equals(warehouseIn.getParams().get("createTimeEnd"))) {
                    warehouseIn.getParams().put("createTimeStart", warehouseIn.getParams().get("createTimeStart") + " 00:00:00");
                    warehouseIn.getParams().put("createTimeEnd", warehouseIn.getParams().get("createTimeEnd") + " 23:59:59");
                }

            }
        }
        return warehouseInMapper.selectWarehouseInList(warehouseIn);
    }

    /**
     * 新增入库单
     *
     * @param warehouseIn 入库单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertWarehouseIn(WarehouseIn warehouseIn) {
        warehouseIn.setCreateTime(DateUtils.getNowDate());

        warehouseIn.setId(Long.valueOf(DateUtils.parseDateToStr("yyyyMMddHHmmss", new Date()) + String.valueOf(ThreadLocalRandom.current().nextInt(1000, 9999))));

        int i = warehouseInMapper.insertWarehouseIn(warehouseIn);

        if (i > 0) {
            Map<String, Object> params = new HashMap<String, Object>(1);
            List<WarehouseInProduct> products = JSON.parseArray(JSON.toJSONString(warehouseIn.getParams().get("products")), WarehouseInProduct.class);
            List<PurchaseOrderProduct> pops = new ArrayList<>(10);
            products.forEach(item -> {
                item.setInId(warehouseIn.getId());

                //修改采购单物品关联的入库数量
                PurchaseOrderProduct pop = new PurchaseOrderProduct();
                pop.setId(item.getPopId());
                pop.setInAmount(item.getQuantity());
                pops.add(pop);
            });
            params.put("products", products);
            warehouseInProductMapper.insertWarehouseInProductBatch(params);

            params.clear();
            //批量修改采购单入库物品数量
            params.put("pops", pops);
            purchaseOrderProductMapper.updatePurchaseOrderProductBatch(params);


            //新增库存记录
            products.forEach(item -> {
                WarehouseStock warehouseStock = new WarehouseStock();
                warehouseStock.setName(item.getName());
                warehouseStock.setDeptId(warehouseIn.getDeptId());
                List<WarehouseStock> warehouseStocks = warehouseStockMapper.selectWarehouseStockList(warehouseStock);
                if (!warehouseStocks.isEmpty()) {
                    //如果有该物品的库存记录，则修改该物品的库存记录
                    WarehouseStock stock = warehouseStocks.get(0);

                    BigDecimal quantity_before = stock.getQuantity();

                    stock.setQuantity(stock.getQuantity().add(item.getQuantity()));
                    warehouseStockMapper.updateWarehouseStock(stock);

                    //新增库存变动记录
                    WarehouseStockRecord stockRecord = getStockRecord(item, quantity_before, stock, PurchaseConstants.StockTypeEnum.In);
                    stockRecord.setDeptId(warehouseIn.getDeptId());
                    warehouseStockRecordMapper.insertWarehouseStockRecord(stockRecord);

                }
                //如果没有该物品的库存记录，则增加该物品的库存记录
                else {
                    WarehouseStock stock = getWarehouseStock(item);
                    stock.setDeptId(warehouseIn.getDeptId());
                    warehouseStockMapper.insertWarehouseStock(stock);

                    //新增库存变动记录
                    WarehouseStockRecord stockRecord = getStockRecord(item, BigDecimal.ZERO, stock, PurchaseConstants.StockTypeEnum.In);
                    stockRecord.setDeptId(warehouseIn.getDeptId());
                    warehouseStockRecordMapper.insertWarehouseStockRecord(stockRecord);
                }
            });

            //修改此采购单的入库状态
            new Thread(new Runnable() {
                @Override
                public void run() {
                    updatePurchaseOrderStatusHandle(warehouseIn.getPurchaseId());
                }
            }).start();

        }

        return i;
    }

    /**
     * 判断添加入库单后，采购单的入库状态是否需要变更
     *
     * @param purchaseId 采购单id
     */
    private void updatePurchaseOrderStatusHandle(Long purchaseId) {
        PurchaseOrderProduct orderProduct = new PurchaseOrderProduct();
        orderProduct.setOrderId(purchaseId);
        List<PurchaseOrderProduct> products = purchaseOrderProductMapper.selectPurchaseOrderProductList(orderProduct);
        BigDecimal purchaseAmount = BigDecimal.ZERO;
        BigDecimal inAmount = BigDecimal.ZERO;
        for (PurchaseOrderProduct product : products) {
            purchaseAmount = purchaseAmount.add(product.getQuantity());
            inAmount = inAmount.add(product.getInAmount());
        }
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setId(purchaseId);
        //未入库
        if (inAmount.compareTo(BigDecimal.ZERO) == 0) {
            purchaseOrder.setWarehouseStatus(PurchaseConstants.WarehouseStatusEnum.ToBeIn);
        }
        //部分入库
        if (inAmount.compareTo(purchaseAmount) < 0) {
            purchaseOrder.setWarehouseStatus(PurchaseConstants.WarehouseStatusEnum.Part);
        }
        //完成入库
        if (inAmount.compareTo(purchaseAmount) == 0) {
            purchaseOrder.setWarehouseStatus(PurchaseConstants.WarehouseStatusEnum.Complete);
        }
        purchaseOrderMapper.updatePurchaseOrder(purchaseOrder);
    }

    private static WarehouseStockRecord getStockRecord(WarehouseInProduct item, BigDecimal quantity_before, WarehouseStock stock, PurchaseConstants.StockTypeEnum stockTypeEnum) {
        WarehouseStockRecord stockRecord = new WarehouseStockRecord();
        stockRecord.setType(stockTypeEnum);
        stockRecord.setName(item.getName());

        stockRecord.setStockBefore(quantity_before);
        stockRecord.setStockAfter(stock.getQuantity());
        stockRecord.setUnit(item.getUnit());
        stockRecord.setfType(item.getfType());
        stockRecord.setfTypeSub(item.getfTypeSub());
        stockRecord.setWhetherImport(item.getWhetherImport());
        stockRecord.setCreateTime(new Date());

        stockRecord.setQuantity(stockRecord.getStockBefore().subtract(stockRecord.getStockAfter()).abs());
        return stockRecord;
    }

    private static WarehouseStock getWarehouseStock(WarehouseInProduct item) {
        WarehouseStock stock = new WarehouseStock();
        stock.setName(item.getName());
        stock.setQuantity(item.getQuantity());
        stock.setUnit(item.getUnit());
        stock.setProduceTime(item.getProduceTime());
        stock.setExpireTime(item.getExpireTime());
        stock.setfType(item.getfType());
        stock.setfTypeSub(item.getfTypeSub());
        stock.setWhetherImport(item.getWhetherImport());
        return stock;
    }

    /**
     * 修改入库单
     *
     * @param warehouseIn 入库单
     * @return 结果
     */
    @Override
    @Transactional
    public int updateWarehouseIn(WarehouseIn warehouseIn) {
        warehouseIn.setUpdateTime(DateUtils.getNowDate());

        List<WarehouseInProduct> products = JSON.parseArray(JSON.toJSONString(warehouseIn.getParams().get("products")), WarehouseInProduct.class);

        int i = warehouseInMapper.updateWarehouseIn(warehouseIn);

        if (i > 0) {
            products.forEach(item -> {
                //查询老的入库数量
                WarehouseInProduct old = warehouseInProductMapper.selectWarehouseInProductById(item.getId());
                warehouseInProductMapper.updateWarehouseInProduct(item);

                //修改对应采购物品关联表的入库数量
                PurchaseOrderProduct orderProduct = purchaseOrderProductMapper.selectPurchaseOrderProductById(item.getPopId());
                BigDecimal subtract = item.getQuantity().subtract(old.getQuantity());
                orderProduct.setInAmount(orderProduct.getInAmount().add(subtract));

                purchaseOrderProductMapper.updatePurchaseOrderProduct(orderProduct);

                //修改库存记录
                WarehouseStock warehouseStock = new WarehouseStock();
                warehouseStock.setName(item.getName());
                warehouseStock.setDeptId(warehouseIn.getDeptId());
                List<WarehouseStock> warehouseStocks = warehouseStockMapper.selectWarehouseStockList(warehouseStock);
                if (!warehouseStocks.isEmpty()) {
                    WarehouseStock stock = warehouseStocks.get(0);
                    BigDecimal quantity_old = stock.getQuantity();
                    stock.setQuantity(stock.getQuantity().add(subtract));
                    warehouseStockMapper.updateWarehouseStock(stock);

                    //新增库存变动记录
                    WarehouseStockRecord stockRecord = getStockRecord(item, quantity_old, stock, PurchaseConstants.StockTypeEnum.In);
                    warehouseStockRecordMapper.insertWarehouseStockRecord(stockRecord);

                } else {
                    WarehouseStock stock = getWarehouseStock(item);
                    stock.setDeptId(warehouseIn.getDeptId());
                    warehouseStockMapper.insertWarehouseStock(stock);

                    //新增库存变动记录
                    WarehouseStockRecord stockRecord = getStockRecord(item, BigDecimal.ZERO, stock, PurchaseConstants.StockTypeEnum.In);
                    stockRecord.setDeptId(warehouseIn.getDeptId());
                    warehouseStockRecordMapper.insertWarehouseStockRecord(stockRecord);

                }


            });
        }

        //修改此采购单的入库状态
        new Thread(new Runnable() {
            @Override
            public void run() {
                updatePurchaseOrderStatusHandle(warehouseIn.getPurchaseId());
            }
        }).start();

        return i;
    }

    /**
     * 批量删除入库单
     *
     * @param ids 需要删除的入库单主键
     * @return 结果
     */
    @Override
    public int deleteWarehouseInByIds(Long[] ids, Long deptId) {
        int i = warehouseInMapper.deleteWarehouseInByIds(ids);

        for (Long id : ids) {
            //根据入库单查询入库单关联物品
            WarehouseInProduct warehouseInProduct = new WarehouseInProduct();
            warehouseInProduct.setInId(id);
            List<WarehouseInProduct> products = warehouseInProductMapper.selectWarehouseInProductList(warehouseInProduct);

            for (WarehouseInProduct product : products) {
                PurchaseOrderProduct orderProduct = purchaseOrderProductMapper.selectPurchaseOrderProductById(product.getPopId());
                //删除入库单关联物品，将入库的数量减掉
                orderProduct.setInAmount(orderProduct.getInAmount().subtract(product.getQuantity()));
                purchaseOrderProductMapper.updatePurchaseOrderProduct(orderProduct);

                //修改库存记录，将库存的东西减掉
                WarehouseStock warehouseStock = new WarehouseStock();
                warehouseStock.setName(product.getName());
                warehouseStock.setDeptId(deptId);
                List<WarehouseStock> warehouseStocks = warehouseStockMapper.selectWarehouseStockList(warehouseStock);
                WarehouseStock stock = warehouseStocks.get(0);
                BigDecimal quantity_old = stock.getQuantity();

                stock.setQuantity(stock.getQuantity().subtract(product.getQuantity()));
                warehouseStockMapper.updateWarehouseStock(stock);

                //新增库存变更记录
                WarehouseStockRecord stockRecord = getStockRecord(product, quantity_old, stock, PurchaseConstants.StockTypeEnum.In_del);
                stockRecord.setDeptId(deptId);
                warehouseStockRecordMapper.insertWarehouseStockRecord(stockRecord);

            }
        }

        //批量删除入库单关联物品记录
        warehouseInProductMapper.deleteWarehouseInProductByInIds(ids);

        return i;
    }

    /**
     * 删除入库单信息
     *
     * @param id 入库单主键
     * @return 结果
     */
    @Override
    public int deleteWarehouseInById(Long id) {
        return warehouseInMapper.deleteWarehouseInById(id);
    }
}
